前兩天,我們知道 STEP 是「食譜」、GLB 是「宅配包裹」,也做好了一份貼滿標籤的減速機積木當試樣。今天第一次真的動手:把這份試樣從食譜轉成宅配包裹。
整個搬家只有三步,用的都是 Day 06 提過的 OCCT 引擎(透過 Python 接頭 OCP):
讀 STEP → 切成三角形貼片 → 寫 GLB
OCCT 是一個很大的工具箱,裡面分成許多功能模組,像引擎裡負責不同工作的零件。OCCT 的類別名稱有個規律:底線前面是模組名,後面才是類別名。這三步各用了一個不同模組裡的類別:
| 步驟 | 引擎裡的類別 | 屬於哪個模組(功能) | 做什麼 |
|---|---|---|---|
| ① 讀 STEP | STEPCAFControl_Reader |
STEPCAFControl:STEP 檔的讀寫,並且保留名稱與顏色 | 把 STEP 讀進來,放上工作台 |
| ② 切貼片 | BRepMesh_IncrementalMesh |
BRepMesh:把精確曲面切成三角形 | 算出三角形,貼在每個面上 |
| ③ 寫 GLB | RWGltf_CafWriter |
RWGltf:glTF 檔的讀寫 | 從工作台寫出 GLB:層級變成節點、CAD 顏色變成材質 |
STEP 檔
│ ① STEPCAFControl_Reader
▼
工作台(XCAF 文件:名稱、顏色、階層、形狀)
│ ② BRepMesh_IncrementalMesh
▼
工作台(多了三角形貼片)
├─▶ 我們自己的程式清點:整理零件清單、改掉重名 ──▶ raw.parts.json
│ ③ RWGltf_CafWriter
▼
raw.glb
也就是說,三個類別是三個不同的引擎功能,各管一段;而「工作台」(XCAF 文件)是它們共用的資料,三步都圍著它轉。
那 raw.parts.json(零件清單)是從哪來的?它不是另一條從 STEP 檔直接產生的路,也不是引擎的第四個步驟,而是我們自己寫的程式,在貼片切好之後、打包之前,把工作台上的東西清點一遍寫成的清單。清點要在打包之前,因為重名零件要先改名,包裹裡的名字才會和清單一致。唯一例外是 STEP 檔頭的資訊(用哪個 AP 版本、從哪個 CAD 匯出):那幾行是直接當文字讀,不經過引擎。
關鍵是這三步在同一個行程、同一個工作台上完成,標籤簿從頭到尾跟著走,所以名字和顏色不會在中途丟失。另外會把零件樹整理成一份清單(raw.parts.json,來源見上圖),格式直接對應 Day 03 講的 asset 契約。
這顆輸出的檔案叫 raw.glb,「raw」代表它是半成品:還沒減面、沒壓縮,方向與單位也還沒轉成網頁慣用的。這幾件事留給後面幾天。
我們拿 Day 06 的減速機試樣實際跑了一次,並且逐項驗收:
| 檢查項目 | 結果 |
|---|---|
| 零件名稱 | 13 個都在 |
| 顏色 | 9 種顏色都在,沒有變成預設白 |
| 整體尺寸 | 和手寫的預期值完全一致 |
| 重複執行 | 兩次結果位元相同 |
| 耗時 / 大小 | 約 1.2 秒 / 118 KB(約 3,300 個三角形) |
坑一:打包工具擅自轉方向與單位。 它預設會把座標換成 glTF 的慣例(Y 軸向上、單位公尺)。Day 05 說過,這個轉換我們規定「只在最後出貨時做一次」,所以要明確設定叫它保持原樣。要驗證也很簡單:把一個子組件往上移 50 公釐,輸出的 GLB 裡位移必須是「Z 方向 50」,不是「Y 方向 50」,也不是「0.05」。
坑二:同名零件。 真實 CAD 常有十顆同名的螺絲。網頁用名字去找(Day 03 提過的 node_path),只會找到第一顆。做法是在寫 GLB 之前,先把重名的改成 Bolt_2、Bolt_3,原本的名字則另外保留。
坑三:位置要一層一層累加。 一個零件在世界裡的位置,等於它自己的位移,加上所屬小盒子的位移,加上大箱子的位移。如果只讀最內層,尺寸就會算錯。我們的試樣所有位移都是零,這個錯誤在試樣上完全看不出來,所以另外造了一個「子組件上移、第二個實例右移」的小組件專門測試。
這份試樣是我們自己畫的,比較乾淨。真實的 SolidWorks 大型組件、幾十 MB 的 STEP,還沒有實測,之後會補。
下一篇要處理 raw.glb 的「肥胖問題」:面數太多,網頁會卡。